﻿using System;
using System.Linq;
using Ninject.Modules;
using System.Collections.Generic;

namespace NazTek.Core
{
    /// <summary>
    /// Encapsulates an array of <see cref="DependencyModule">dependency map</see>s.
    /// </summary>
    public sealed class DependencyModuleArray : IDisposable
    {
        /// <summary>
        /// Sets the <see cref="Modules"/> with supplied value.
        /// </summary>
        /// <param name="modules">The modules value to set.</param>
        public DependencyModuleArray(params DependencyModule[] modules)
        {
            if (modules != null && modules.Length > 0)
                Modules = modules;
        }
        /// <summary>
        /// Disposes each non null module in <see cref="Modules"/>.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }
        /// <summary>
        /// Converts maps in <see cref="Modules"/> to underlying container modules.
        /// </summary>
        /// <returns>Underlying container module array.</returns>
        internal INinjectModule[] ToNinjectModules()
        {
            return ToNinjectModuleList().ToArray();
        }
        /// <summary>
        /// Converts maps in <see cref="Modules"/> to underlying container module list.
        /// </summary>
        /// <returns>Underlying container module list.</returns>
        internal List<INinjectModule> ToNinjectModuleList()
        {
            return Modules.ToList().Select(m => m.Core).ToList();
        }
        /// <summary>
        /// Converts maps in <see cref="Modules"/> to underlying container module list, by implementation type.
        /// </summary>
        /// <returns>Underlying container module list, by implementation type.</returns>
        /// <remarks>The operation is necessary for disposing the modules.</remarks>
        internal List<NinjectModule> ToConcreteNinjectModuleList()
        {
            return Modules.ToList().Select(m => m.ConcreteCore).ToList();
        }
        /// <summary>
        /// Gets the number of <see cref="Modules"/> available.
        /// </summary>
        internal int Length { get { return Modules.Length; } }
        /// <summary>
        /// Gets/sets registration maps.
        /// </summary>
        private DependencyModule[] Modules { get; set; }
        /// <summary>
        /// Frees managed and native resources.
        /// </summary>
        /// <param name="disposing">Disposes managed resource items in <see cref="Modules"/>, when true.</param>
        private void Dispose(bool disposing)
        {
            if (!disposing || Modules == null || Modules.Length == 0)
                return;
            foreach (var m in Modules.Where(m => m != null))
                m.Dispose();
            Modules = null;
        }
    }
}